package com.woniu.defecttracking.filter;

import com.woniu.defecttracking.entity.AccountDetails;
import com.woniu.defecttracking.exception.LoginErrorHandler;
import com.woniu.defecttracking.mapper.ResourceMapper;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class AccessFilter extends OncePerRequestFilter {

    private LoginErrorHandler loginErrorHandler;

    private StringRedisTemplate srt;

    private ResourceMapper resourceMapper;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    public AccessFilter(LoginErrorHandler handler, StringRedisTemplate srt, ResourceMapper resourceMapper){
        this.loginErrorHandler=handler;
        this.srt=srt;
        this.resourceMapper=resourceMapper;
    }

    public AccessFilter(){
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        AccountDetails accountDetails=null;
        try {
            accountDetails = (AccountDetails) SecurityContextHolder
                    .getContext().getAuthentication().getPrincipal();
        }catch (Exception e){
            filterChain.doFilter(request,response);
            return;
        }
        String uri = request.getRequestURI();
        List<String> urls = srt.opsForList()
                .range("resource:url:accountId:" + accountDetails.getAccountId(), 0, -1);
        if (urls==null||urls.size()<=0){
            urls= resourceMapper.selectResourceByAccount(accountDetails.getAccountId());
            srt.opsForList().leftPushAll("resource:url:accountId:"+accountDetails.getAccountId(),urls);
            srt.expire("resource:url:accountId:"+accountDetails.getAccountId(),2, TimeUnit.HOURS);
            filterChain.doFilter(request,response);
        }else {
            Boolean bool = false;
            for (String url:urls){
                if (antPathMatcher.match(url, uri)){
                    bool=true;
                    break;
                }
            }
            if (bool){
                filterChain.doFilter(request,response);
            }else {
                loginErrorHandler.onAuthenticationFailure(request,response,new InternalAuthenticationServiceException("没有访问权限"));
            }
        }

    }
}
